import os
import logging
from logging.handlers import RotatingFileHandler
from flask import Flask, request, jsonify, send_from_directory
from flask_migrate import Migrate
from .models import db, Student, Teacher, Admin
from werkzeug.security import generate_password_hash, check_password_hash
import jwt
import datetime

def create_app():
    base_dir = os.path.abspath(os.path.dirname(os.path.dirname(__file__)))
    app = Flask(
        __name__,
        instance_relative_config=True,
        static_folder='../static',
        template_folder=os.path.join(base_dir, 'templates')
    )
    
    # 配置
    app.config['SQLALCHEMY_DATABASE_URI'] = 'mysql+pymysql://lpy:lpylpylpy@localhost:3308/award_records'
    app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False
    app.config['SECRET_KEY'] = '708090'
    
    # 日志配置
    if not app.debug and not app.testing:
        if not os.path.exists('logs'):
            os.mkdir('logs')
        file_handler = RotatingFileHandler('logs/student_honor.log', maxBytes=10240, backupCount=10)
        file_handler.setFormatter(logging.Formatter(
            '%(asctime)s %(levelname)s: %(message)s [in %(pathname)s:%(lineno)d]'
        ))
        file_handler.setLevel(logging.INFO)
        app.logger.addHandler(file_handler)
        app.logger.setLevel(logging.INFO)
        app.logger.info('学生荣誉信息管理系统启动')
    
    db.init_app(app)
    Migrate(app, db)

    # 注册蓝图，页面和API分离
    from .student import student_page_bp, student_api_bp
    from .teacher import teacher_page_bp, teacher_api_bp
    from .admin import admin_bp
    from .admin.routes import admin_api_bp
    
    app.register_blueprint(student_page_bp, url_prefix='/student')
    app.register_blueprint(student_api_bp, url_prefix='/api/student')
    app.register_blueprint(teacher_page_bp, url_prefix='/teacher')
    app.register_blueprint(teacher_api_bp, url_prefix='/api/teacher')
    app.register_blueprint(admin_bp, url_prefix='/admin')
    app.register_blueprint(admin_api_bp, url_prefix='/api/admin')

    # 全局错误处理
    @app.errorhandler(404)
    def not_found_error(error):
        return jsonify({'code': 404, 'msg': '页面未找到'}), 404

    @app.errorhandler(500)
    def internal_error(error):
        db.session.rollback()
        app.logger.error(f'服务器内部错误: {error}')
        return jsonify({'code': 500, 'msg': '服务器内部错误'}), 500

    @app.errorhandler(Exception)
    def handle_exception(e):
        app.logger.error(f'未处理的异常: {e}')
        return jsonify({'code': 500, 'msg': '系统错误'}), 500

    @app.route('/')
    def index():
        return app.send_static_file('index.html')

    @app.route('/api/register', methods=['POST'])
    def register():
        try:
            data = request.get_json()
            role = data.get('role')
            username = data.get('username')
            name = data.get('name')
            gender = data.get('gender')
            password = data.get('password')
            confirm = data.get('confirm')
            grade = data.get('grade')
            class_name = data.get('class_name')
            department = data.get('department')
            phone = data.get('phone')
            email = data.get('email')

            if not all([role, username, name, gender, password, confirm]):
                return jsonify({'code': 400, 'msg': '信息填写不完整'}), 400
            if password != confirm:
                return jsonify({'code': 400, 'msg': '两次输入的密码不一致'}), 400

            if role == 'student':
                if Student.query.filter_by(username=username).first():
                    return jsonify({'code': 400, 'msg': '用户名已存在'}), 400
                student = Student(
                    username=username,
                    name=name,
                    gender=gender,
                    grade=grade,
                    class_name=class_name,
                    department=department,
                    phone=phone,
                    email=email
                )
                student.set_password(password)
                db.session.add(student)
                db.session.commit()
                app.logger.info(f'学生注册成功: {username}')
                return jsonify({'code': 200, 'msg': '注册成功'})
            elif role == 'teacher':
                if Teacher.query.filter_by(username=username).first():
                    return jsonify({'code': 400, 'msg': '用户名已存在'}), 400
                teacher = Teacher(
                    username=username,
                    name=name,
                    gender=gender,
                    department=department,
                    phone=phone,
                    email=email,
                    is_approved=False,
                    approval_status='pending'
                )
                teacher.set_password(password)
                db.session.add(teacher)
                db.session.commit()
                app.logger.info(f'教师注册成功: {username}')
                return jsonify({'code': 200, 'msg': '注册成功，请等待管理员审核'})
            else:
                return jsonify({'code': 400, 'msg': '不支持的角色'}), 400
        except Exception as e:
            app.logger.error(f'注册失败: {e}')
            db.session.rollback()
            return jsonify({'code': 500, 'msg': '注册失败，请重试'}), 500

    @app.route('/api/login', methods=['POST'])
    def login():
        try:
            data = request.get_json()
            role = data.get('role')
            username = data.get('username')
            password = data.get('password')
            
            # 管理员登录
            if role == 'admin':
                admin = Admin.query.filter_by(username=username).first()
                if admin and admin.check_password(password):
                    token = jwt.encode({
                        'admin_id': admin.id,
                        'role': 'admin',
                        'exp': datetime.datetime.utcnow() + datetime.timedelta(hours=2)
                    }, app.config['SECRET_KEY'], algorithm='HS256')
                    if isinstance(token, bytes):
                        token = token.decode('utf-8')
                    app.logger.info(f'管理员登录成功: {username}')
                    return jsonify({'code': 200, 'msg': '登录成功', 'token': token, 'role': 'admin'})
                else:
                    app.logger.warning(f'管理员登录失败: {username}')
                    return jsonify({'code': 401, 'msg': '用户名或密码错误'}), 401
            # 学生登录
            elif role == 'student':
                student = Student.query.filter_by(username=username).first()
                if student and student.check_password(password):
                    token = jwt.encode({
                        'user_id': student.id,
                        'role': 'student',
                        'exp': datetime.datetime.utcnow() + datetime.timedelta(hours=2)
                    }, app.config['SECRET_KEY'], algorithm='HS256')
                    if isinstance(token, bytes):
                        token = token.decode('utf-8')
                    app.logger.info(f'学生登录成功: {username}')
                    return jsonify({'code': 200, 'msg': '登录成功', 'token': token, 'role': 'student'})
                else:
                    app.logger.warning(f'学生登录失败: {username}')
                    return jsonify({'code': 401, 'msg': '用户名或密码错误'}), 401
            # 教师登录
            elif role == 'teacher':
                teacher = Teacher.query.filter_by(username=username).first()
                if teacher and teacher.check_password(password):
                    if not teacher.is_approved:
                        if teacher.approval_status == 'pending':
                            app.logger.info(f'教师登录被拒绝(审核中): {username}')
                            return jsonify({'code': 403, 'msg': '您的账号正在审核中，请耐心等待', 'status': 'pending'}), 403
                        elif teacher.approval_status == 'rejected':
                            app.logger.info(f'教师登录被拒绝(审核未通过): {username}')
                            return jsonify({'code': 403, 'msg': '您的账号审核未通过，请联系管理员', 'status': 'rejected'}), 403
                    token = jwt.encode({
                        'user_id': teacher.id,
                        'role': 'teacher',
                        'exp': datetime.datetime.utcnow() + datetime.timedelta(hours=2)
                    }, app.config['SECRET_KEY'], algorithm='HS256')
                    if isinstance(token, bytes):
                        token = token.decode('utf-8')
                    app.logger.info(f'教师登录成功: {username}')
                    return jsonify({'code': 200, 'msg': '登录成功', 'token': token, 'role': 'teacher'})
                else:
                    app.logger.warning(f'教师登录失败: {username}')
                    return jsonify({'code': 401, 'msg': '用户名或密码错误'}), 401
            else:
                return jsonify({'code': 400, 'msg': '不支持的角色'}), 400
        except Exception as e:
            app.logger.error(f'登录失败: {e}')
            return jsonify({'code': 500, 'msg': '登录失败，请重试'}), 500

    return app 